"""
物体检测器封装
统一的物体检测接口
"""
import cv2
import numpy as np
import logging
import time
from typing import List, Tuple, Optional

from utils.yolo_shape_detector import YOLO11ShapeDetect

logger = logging.getLogger(__name__)


class ObjectDetector:
    """
    物体检测器主类
    封装YOLO11物体检测功能，提供简洁的检测接口
    """
    
    def __init__(self, model_path: str, conf_threshold: float = 0.7, iou_threshold: float = 0.45):
        """
        初始化物体检测器
        
        Args:
            model_path: 模型文件路径
            conf_threshold: 置信度阈值
            iou_threshold: IOU阈值
        """
        self.model_path = model_path
        self.conf_threshold = conf_threshold
        self.iou_threshold = iou_threshold
        
        # 初始化检测器
        self.detector = None
        self._init_detector()
        
        logger.info(f"✅ 物体检测器初始化完成")
        logger.info(f"模型路径: {model_path}")
        logger.info(f"置信度阈值: {conf_threshold}, IOU阈值: {iou_threshold}")
    
    def _init_detector(self):
        """初始化YOLO检测器"""
        try:
            self.detector = YOLO11ShapeDetect(
                model_file=self.model_path,
                conf=self.conf_threshold,
                iou=self.iou_threshold
            )
            logger.info("YOLO11检测器初始化成功")
            
        except Exception as e:
            logger.error(f"检测器初始化失败: {e}")
            self.detector = None
            raise
    
    def detect(self, frame: np.ndarray) -> dict:
        """
        检测物体
        
        Args:
            frame: 输入图像帧
            
        Returns:
            dict: 检测结果，包含 boxes, class_ids, confidences, inference_time, object_count
        """
        if self.detector is None:
            logger.warning("检测器未初始化")
            return {
                'boxes': [],
                'class_ids': [],
                'confidences': [],
                'inference_time': 0.0,
                'object_count': 0,
                'success': False,
                'error': '检测器未初始化'
            }
        
        try:
            # 执行检测
            boxes, class_ids, confidences, inference_time, object_count = self.detector.detect_shapes(frame)
            
            return {
                'boxes': boxes,
                'class_ids': class_ids,
                'confidences': confidences,
                'inference_time': inference_time,
                'object_count': object_count,
                'success': True,
                'error': None
            }
            
        except Exception as e:
            logger.error(f"物体检测失败: {e}")
            return {
                'boxes': [],
                'class_ids': [],
                'confidences': [],
                'inference_time': 0.0,
                'object_count': 0,
                'success': False,
                'error': str(e)
            }
    
    def draw_results(self, frame: np.ndarray, detection_result: dict, 
                    show_boxes: bool = True, show_center: bool = True, show_stats: bool = True) -> np.ndarray:
        """
        在图像上绘制检测结果
        
        Args:
            frame: 输入图像
            detection_result: 检测结果
            show_boxes: 是否显示检测框
            show_center: 是否显示中心点
            show_stats: 是否显示统计信息
            
        Returns:
            np.ndarray: 绘制后的图像
        """
        if not detection_result.get('success', False):
            # 检测失败，显示错误信息
            result_frame = frame.copy()
            if show_stats:
                error_text = detection_result.get('error', '检测失败')
                cv2.putText(result_frame, f"Error: {error_text}", (10, 30), 
                           cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            return result_frame
        
        # 使用检测器绘制结果
        if self.detector:
            return self.detector.draw_detections(
                frame, 
                detection_result['boxes'], 
                detection_result.get('class_ids', []),
                detection_result.get('confidences', []),
                show_boxes=show_boxes,
                show_center=show_center, 
                show_stats=show_stats
            )
        else:
            return frame
    
    def get_stats(self) -> dict:
        """获取检测统计信息"""
        if self.detector:
            return self.detector.get_stats()
        return {}
    
    def get_largest_object(self, boxes: List[List[int]]) -> Optional[List[int]]:
        """
        获取最大的物体框
        
        Args:
            boxes: 物体边界框列表
            
        Returns:
            Optional[List[int]]: 最大物体框，如果没有则返回None
        """
        if not boxes:
            return None
        
        largest_area = 0
        largest_box = None
        
        for box in boxes:
            x1, y1, x2, y2 = box
            area = (x2 - x1) * (y2 - y1)
            if area > largest_area:
                largest_area = area
                largest_box = box
        
        return largest_box
    
    def get_object_center(self, box: List[int]) -> Tuple[int, int]:
        """
        获取物体框的中心点
        
        Args:
            box: 物体边界框 [x1, y1, x2, y2]
            
        Returns:
            Tuple[int, int]: 中心点坐标 (x, y)
        """
        x1, y1, x2, y2 = box
        center_x = (x1 + x2) // 2
        center_y = (y1 + y2) // 2
        return center_x, center_y